program mailbox_example;

    class Car;
        mailbox mb_speed, mb_fuel;
        int sample_period;

        function new(int period = $urandom());
            // mailbox 在创建时可以指定大小，默认为0(表示不限容量)
            mb_speed = new();
            mb_fuel = new();
            sample_period = period;
        endfunction

        task sensor_speed();
            int speed;
            forever begin
                if (std::randomize(speed) with { speed inside {[64:100]}; }) begin
                    // mailbox 的 put 方法是堵塞的，直到有空间可用
                    mb_speed.put(speed);
                    // try_put 方法是非堵塞的，如果没有空间则返回失败
                end
                else begin
                    $display("Car: Failed to generate speed");
                end
                #sample_period;
            end
        endtask

        task sensor_fuel();
            int fuel;
            forever begin
                if (std::randomize(fuel) with { fuel inside {[0:100]}; }) begin
                    mb_fuel.put(fuel);
                end
                else begin
                    $display("Car: Failed to generate fuel");
                end
                #sample_period;
            end
        endtask
        
        task monitor(mailbox mb, string name);
            int data;
            forever begin
                // mailbox 的 get方法会阻塞，直到有数据可用
                mb.get(data);
                // try_get 方法是非阻塞的，如果没有数据则返回失败
                $display("@%g: Car::%s is %0d", $time, name, data);
            end
        endtask

        task driver();
            fork 
                sensor_speed();
                sensor_fuel();
                monitor(mb_speed, "speed");
                monitor(mb_fuel, "fuel");
            join_none
        endtask
    endclass

    initial begin
        // 创建汽车对象并启动传感器和监控任务
        automatic Car car = new(5);
        car.driver();
        #100; $finish; 
    end
endprogram
